/*
 * Created by SharpDevelop.
 * User: MyWife
 * Date: 5/18/2008
 * Time: 11:18 AM
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
 using System.Windows.Forms;
 using System.Drawing;
 using System.Data;
 using System.Collections;
 using System;
 using System.Diagnostics;
 using System.Runtime.InteropServices;
 using System.IO;
 using System.Reflection;
 using System.Drawing.Imaging;
 using System.Configuration;
 using System.Text;
 using System.Threading;
 using popLib.Resource;
 using System.ComponentModel;
 using popLib.ExtensionClass;
 namespace popLib
 {
 
	 public class FormLib{
	 	
	 	
 		
 		#region ShowLoading - hideLoading
	 	//show loading panel on passed form
	 	public static bool showLoading(Control container, string content)
		{
			Label loading = null;	 		
	 		for(int i=0;i<container.Controls.Count;i++){
				if( container.Controls[i].Name == "spl_loading8956" )
				{
					loading = (Label)container.Controls[i];
					break;
				}
	 		}
	
			if( loading == null ){
				loading	  = new Label();
				container.Controls.Add(loading);
			}
			
			loading.BorderStyle = BorderStyle.FixedSingle;
			loading.Name      = "spl_loading8956";
			loading.Text	  = content;			
			loading.TextAlign = ContentAlignment.MiddleCenter;
			loading.AutoSize  = true;
			loading.Padding   = new Padding(10);
			loading.Location  = new Point((container.Width - loading.Width)/2, (container.Height - loading.Height)/2 );
			loading.Visible   = true;
	
			loading.BringToFront();
			container.Update();
			return true;
		}
	
	 	//hide loading panel on passed form
		public static void hideLoading(Control container)
		{
			for(int i=0;i<container.Controls.Count;i++)
				if( container.Controls[i].Name == "spl_loading8956" )
				{
					container.Controls[i].Visible = false;
					break;
				}	
		}
		#endregion
	
		#region Alert - Confirm 
		//show message box with specified caption
		public static void alert(object message, object caption){
			MessageBox.Show(message+"", caption+"");
		}
	
		//show message box
		public static void alert(object message)
		{
			MessageBox.Show(message+"", "Message");
		}
		
		//show confirm message box with caption
		public static bool confirm(object message, object caption){
			if(MessageBox.Show(message+"", caption+"",MessageBoxButtons.OKCancel).ToString()=="OK") return true;
			return false;
		}
		
		///show confirm message box
		public static bool confirm(object message)
		{
			if(MessageBox.Show(message+"", "Confirmation",MessageBoxButtons.OKCancel).ToString()=="OK") return true;
			return false;
		}
		/// <summary>
		/// MessageBoxButtons for confirmChoice function 
		/// </summary>
				
		/// <summary>
		/// Show confirm message box with button type is customized
		/// </summary>
		/// <param name="message"></param>
		/// <param name="buttonType"></param>
		/// <returns></returns>
		public static ConfirmResult confirmChoice(object message, ConfirmButton buttonType)			
		{
			return confirmChoice( message, "Confirmation", buttonType );			
		}
		
		
		/// <summary>
		/// Show confirm message box with caption & button type are customized
		/// </summary>
		/// <param name="message"></param>
		/// <param name="buttonType"></param>
		/// <returns></returns>
		public static ConfirmResult confirmChoice(object message, object caption, ConfirmButton buttonType)			
		{
			MessageBoxButtons Msgbutton = MessageBoxButtons.OKCancel;
			switch( buttonType ){
				case ConfirmButton.OK: 					Msgbutton = MessageBoxButtons.OK; break;
				case ConfirmButton.OKCancel: 			Msgbutton = MessageBoxButtons.OKCancel; break;
				case ConfirmButton.RetryCancel: 		Msgbutton = MessageBoxButtons.RetryCancel; break;
				case ConfirmButton.YesNo: 				Msgbutton = MessageBoxButtons.YesNo; break;
				case ConfirmButton.YesNoCancel: 		Msgbutton = MessageBoxButtons.YesNoCancel; break;
				case ConfirmButton.AbortRetryIgnore: 	Msgbutton = MessageBoxButtons.AbortRetryIgnore; break;
			}
			
			switch( MessageBox.Show(message+"", caption+"", Msgbutton).ToString() ){
				case "OK": return ConfirmResult.OK; 
				case "Cancel": return ConfirmResult.Cancel;
				case "Yes": return ConfirmResult.Yes; 
				case "No": return ConfirmResult.No; 
				case "Abort": return ConfirmResult.Abort; 
				case "Retry": return ConfirmResult.Retry; 
				case "Ignore": return ConfirmResult.Ignore;
				default: return ConfirmResult.None;
			}
			
		}
		#endregion
				
		#region Open, save file dialog		
		/// <summary>
		/// Show the OpenFileDialog to open single file
		/// </summary>
		/// <param name="filter">file filter like "All files(*.*)|*.*"</param>
		/// <param name="initPath">Path to open file</param>
		/// <param name="multiSelect">select multi file or not</param>
		/// <returns></returns>
		public static ReturnSet openFile(string filter, string initPath, bool multiSelect ){
			OpenFileDialog openFileDialog = new OpenFileDialog();
			openFileDialog.Filter = StringLib.isValid(filter) ? filter : "All files(*.*)|*.*" ;
			openFileDialog.Multiselect = multiSelect;
			
			if( StringLib.isValid(initPath) ){
				
				if( File.Exists(initPath) )
					initPath = Path.GetDirectoryName(initPath);
				
				if( Directory.Exists(initPath) )
					openFileDialog.InitialDirectory = initPath;
			}
			
			if( openFileDialog.ShowDialog()+"" == "OK"){
				if( multiSelect )
					return new ReturnSet( true, openFileDialog.FileNames );
				return new ReturnSet( true, openFileDialog.FileName );
			}
			return new ReturnSet();
		}
		public static ReturnSet openFile(){
			return openFile(null, null, false);
		}		
		public static ReturnSet openFile(string filter ){
			return openFile(filter, null, false);
		}
		public static ReturnSet openFile(string filter, string initPath){
			return openFile(filter, initPath, false);
		}
		public static ReturnSet openFile(string filter, bool multiSelect){
			return openFile(filter, null, multiSelect);
		}		
		
		/// <summary>
		/// Show the SaveFileDialog to save file
		/// </summary>
		/// <param name="filter">file filter like "All files(*.*)|*.*"</param>
		/// <returns></returns>
		public static string saveFile(string filter){
			return saveFile( filter, null );
		}
		
		/// <summary>
		/// Show the SaveFileDialog to save file
		/// </summary>
		/// <param name="filter">file filter like "All files(*.*)|*.*"</param>
		/// <param name="defaultFile">default file name you suggest to save</param>
		/// <returns></returns>
		public static string saveFile(string filter, string defaultFile){
			SaveFileDialog saveFileDialog = new SaveFileDialog();
			if( StringLib.isValid(defaultFile) )
				saveFileDialog.FileName = defaultFile;
			saveFileDialog.Filter = filter;			
			if( saveFileDialog.ShowDialog()+"" == "OK")
				return saveFileDialog.FileName;
			return null;;
		}
		
		/// <summary>
		/// Show FolderBrowserDialog to select a folder
		/// </summary>
		/// <param name="rootFolder"></param>
		/// <param name="showNewFolderButton"></param>
		/// <returns></returns>
		public static ReturnSet folderBrowser( System.Environment.SpecialFolder rootFolder, bool showNewFolderButton){
			ReturnSet result = new ReturnSet(false, null);
			FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog();
			folderBrowserDialog.RootFolder = rootFolder;
			folderBrowserDialog.ShowNewFolderButton = showNewFolderButton;			
			if( folderBrowserDialog.ShowDialog()+"" == "OK")
				result = new ReturnSet(true, folderBrowserDialog.SelectedPath);
			return result;			
		}
		
		/// <summary>
		/// Show FolderBrowserDialog to select a folder
		/// </summary>		
		/// <returns></returns>
		public static ReturnSet folderBrowser(){			
			return folderBrowser(System.Environment.SpecialFolder.Desktop, true);
		}
		#endregion
		
		#region Control functions( list, match )
		/// <summary>
		/// Get all controls in the ControlCollection
		/// </summary>
		/// <param name="controls"></param>
		/// <returns></returns>
		public static Control[] getChildControlList( System.Windows.Forms.Control.ControlCollection controls ){
			ArrayList list = new ArrayList();
			
			list.AddRange( controls );
			
			for(int i=0;i<controls.Count;i++){
				if( matchControlType( controls[i], new ControlType[]{
				                     					ControlType.TabPage,
				                     					ControlType.TabControl, 
				                     					ControlType.Panel, 
				                     					ControlType.GroupBox, 
				                     					ControlType.TableLayoutPanel, 
				                     					ControlType.SplitContainer,
				                     					ControlType.SplitterPanel,
				                     					ControlType.FlowLayoutPanel
				                     					} )  )
					list.AddRange( getChildControlList( controls[i].Controls ) );
				
			}
			Control[] result = new Control[list.Count];
			list.CopyTo( result );
			return result;			
		}
		
		/// <summary>
		/// Get all controls in the control container ( Panel, GroupBox, TabControl, TabPage )
		/// </summary>
		/// <param name="controls"></param>
		/// <returns></returns>
		public static Control[] getChildControlList( Control container ){
			return getChildControlList( container.Controls );
		}
		
		
		/// <summary>
		/// Check if the control has type matches any of the array ControlType.
		/// </summary>
		/// <param name="control"></param>
		/// <param name="controlTypes"></param>
		/// <returns></returns>
		public static bool matchControlType(object control, ControlType[] controlTypes){
			ControlType compareType = getControlType( control );
			foreach( ControlType eachType in controlTypes )
				if( eachType == compareType ) return true;
			return false;			
		}
		
		public static bool matchControlType(object control, ControlType controlType){
			ControlType compareType = getControlType( control );			
			if( controlType == compareType ) return true;
			return false;			
		}
		
		
		/// <summary>
		/// Get type name of the control & return enum ControlType.
		/// </summary>
		/// <param name="control"></param>
		/// <returns></returns>
		public static ControlType getControlType(object control){
			try{				
				string controlType = control.GetType().ToString().Replace("System.Windows.Forms.","");
				return (ControlType) Enum.Parse(typeof(ControlType), controlType, true);
			}catch(Exception ex){ex.ToString();}
			return ControlType.None;
		}
		
		
		public delegate void ExecuteDragAndDrop(Control control, string[] items );
		public static void dragAndDrop( Control control, ExecuteDragAndDrop dlgFunc ){
			control.AllowDrop = true;
			control.DragEnter += delegate(object sender, DragEventArgs e) { 
				if(e.Data.GetDataPresent(DataFormats.FileDrop))
					e.Effect = DragDropEffects.All;
				else
					e.Effect = DragDropEffects.None;
			};
			
			control.DragDrop += delegate(object sender, DragEventArgs e) { 
				string[] items = (string[]) e.Data.GetData(DataFormats.FileDrop, false);
				dlgFunc( control, items );
			};
		}
		#endregion
				
		#region Form Functions
		public static void bringToFront(string className,string CaptionName)
        {
        	APILib.SetForegroundWindow( APILib.FindWindow(className,CaptionName));
        }
		
		public static void extractEmbedResource( string resourceName, string fileDestination ){
			Assembly assembly 		= Assembly.GetCallingAssembly();
			Stream readStream 		= assembly.GetManifestResourceStream(resourceName);
			FileStream writeStream 	= new FileStream( fileDestination, FileMode.Create, FileAccess.Write );
			FileLib.copyStream( readStream, writeStream );
			readStream.Close();
			writeStream.Close();			
		}
		
		public static void viewProgressBar( string text, int percent, ProgressBar pgbar, Form formContainer ){
			ThreadStart ts = delegate{
				pgbar.Value = percent > 100 ? 100: percent;
	            string content = (StringLib.isValid(text) ? text + " - " + percent : percent.ToString()) + "%";
	            using (Graphics gr = pgbar.CreateGraphics())
	            {
	                gr.DrawString(content,
	                    SystemFonts.DefaultFont,
	                    Brushes.Black,
	                    new PointF(
	                        pgbar.Width / 2 - (gr.MeasureString(content, SystemFonts.DefaultFont).Width / 2.0F),
	                        pgbar.Height / 2 - (gr.MeasureString(content, SystemFonts.DefaultFont).Height / 2.0F)
	                    )
	               );
	            }
	            formContainer.Refresh();
			};
			formContainer.Invoke(ts);
		}
		
		public static void setMergeColumn(DataGridView dgv, MergeHeaderInfo[] mergeInfos){
			dgv.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.EnableResizing;
			bool doubleHeader = false;
			foreach( MergeHeaderInfo mergeInfo in mergeInfos ){
				if( mergeInfo.SplitRow ){
					doubleHeader = true;
					break;
				}
			}
			
			if( doubleHeader ){
				dgv.ColumnHeadersHeight = dgv.ColumnHeadersHeight * 2;
			}
			
			#region CellPainting event
			dgv.CellPainting += delegate(object sender, DataGridViewCellPaintingEventArgs e) {
				if (e.RowIndex == -1 && e.ColumnIndex > -1)
	            {
	                Rectangle r2 = e.CellBounds;	                
	                e.PaintBackground(r2, true);               
	                e.PaintContent(r2);
	                e.Handled = true;
	            }
			};
			#endregion
			
			#region Pain event
			dgv.Paint += delegate(object sender, PaintEventArgs e) {
				foreach( MergeHeaderInfo mergeInfo in mergeInfos ){
					
					//get first column height and location
					Rectangle headerBox = dgv.GetCellDisplayRectangle(mergeInfo.LeftColumn, -1,true);
					headerBox.X += 1;
					headerBox.Y += 1;
					headerBox.Width -= 3;
					
					if( mergeInfo.SplitRow )	headerBox.Height = headerBox.Height / 2 - 1;
					else headerBox.Height = headerBox.Height - 1;
					
					//append width from others column
					for( int i = mergeInfo.LeftColumn; i <= mergeInfo.RightColumn; i++ ){
						if( i >= dgv.Columns.Count )
							continue;						
						if( i != mergeInfo.LeftColumn )
							headerBox.Width += dgv.GetCellDisplayRectangle(i, -1,true).Width;
						if( mergeInfo.SplitRow )
							dgv.Columns[i].HeaderCell.Style.Alignment = DataGridViewContentAlignment.BottomCenter;
					}
					
					
					//draw background
					if( mergeInfo.SplitRow )
						e.Graphics.FillRectangle(new SolidBrush(SystemColors.ActiveBorder), headerBox);
					
					headerBox.Height -= 1;
					e.Graphics.FillRectangle(new SolidBrush(dgv.ColumnHeadersDefaultCellStyle.BackColor), headerBox);
					
					//draw string
					StringFormat format = new StringFormat();
	                format.Alignment = StringAlignment.Center;
	                format.LineAlignment = StringAlignment.Center;
	                
	                e.Graphics.DrawString(	mergeInfo.HeaderText,
	                    					dgv.ColumnHeadersDefaultCellStyle.Font,
						                    new SolidBrush(dgv.ColumnHeadersDefaultCellStyle.ForeColor),
						                    headerBox,
						                    format);
	                
					
				}
			};
			#endregion
				
			#region ColumnWidthChanged event
			dgv.ColumnWidthChanged += delegate(object sender, DataGridViewColumnEventArgs e) { 
				Rectangle rtHeader = dgv.DisplayRectangle;
	            //if( doubleHeader ) rtHeader.Height = dgv.ColumnHeadersHeight / 2;
	            dgv.Invalidate(rtHeader);
			};
			#endregion
			
			#region Scroll event
			dgv.Scroll += delegate(object sender, ScrollEventArgs e) { 
				Rectangle rtHeader = dgv.DisplayRectangle;
	            //if( doubleHeader ) rtHeader.Height = dgv.ColumnHeadersHeight / 2;
	            dgv.Invalidate(rtHeader);
			};		
			#endregion				
		}
		
		#region moveForm
		
		public static void moveForm(Control control , StickBorderType stickBorder){
			moveForm( control, control, stickBorder );
		}
		
		public static void moveForm(Control control, Control container, StickBorderType stickBorder){
			control.MouseDown += delegate(object sender, MouseEventArgs e) { 
				const int WM_NCLBUTTONDOWN = 0xA1;
				const int HT_CAPTION = 0x2;
				if (e.Button == MouseButtons.Left)
				{
				    APILib.ReleaseCapture();
				    APILib.SendMessage( container.Handle , WM_NCLBUTTONDOWN, HT_CAPTION, 0);
				}
			};
			
			if(stickBorder != StickBorderType.None) control.MouseMove += delegate{
				stickControlBorder( container, stickBorder, 20 );
			};
		}
		
		public static void stickControlBorder( Control control, StickBorderType stickBorder, int minimumDistance ){
			int currentX  = control.Location.X;
			int currentY  = control.Location.Y;
			int scrWidth  = Screen.PrimaryScreen.Bounds.Width;
			int scrHeight = Screen.PrimaryScreen.Bounds.Height;	
			
			switch( stickBorder ){
				case StickBorderType.Left: 	currentX = (currentX < minimumDistance) ? 0 : currentX; break;
				case StickBorderType.Right: currentX = (currentX > (scrWidth-control.Width)-minimumDistance) ? scrWidth-control.Width : currentX; break;
				case StickBorderType.Top: 	currentY = (currentY < minimumDistance) ? 0 : currentY; break;
				case StickBorderType.Bottom:currentY = (currentY > (scrHeight-control.Height)-minimumDistance) ? scrHeight-control.Height : currentY; break;
				case StickBorderType.All:
					currentX = (currentX < minimumDistance) ? 0 : currentX;
					currentX = (currentX > (scrWidth-control.Width)-minimumDistance) ? scrWidth-control.Width : currentX;
					currentY = (currentY < minimumDistance) ? 0 : currentY;
					currentY = (currentY > (scrHeight-control.Height)-minimumDistance) ? scrHeight-control.Height : currentY;
					break;
			}
			
			if( currentX != control.Location.X || currentY != control.Location.Y ){
				control.Location = new Point( currentX, currentY );
				
			}
		}
		#endregion
				
		#region moveFormEvent		
		public static void moveFormEvent(Control control, StickBorderType stickBorder){
			moveFormEvent( control, control, stickBorder );
		}
		
		public static void moveFormEvent(Control control, Control container, StickBorderType stickBorder){
			bool dragging 		= false;
			Point pointClicked 	= new Point(0,0);
			
			control.MouseDown += delegate(object sender, MouseEventArgs e) {
				if (e.Button == MouseButtons.Left){
					dragging = true;
	            	pointClicked = new Point(e.X, e.Y);
		        }else dragging = false;
			};
			control.MouseMove += delegate(object sender, MouseEventArgs e) {
				if (dragging){
	            	container.Location = new Point( container.Left - (pointClicked.X - e.X), container.Top - (pointClicked.Y - e.Y));	            	
	        	}
			};
			control.MouseUp	  += delegate(object sender, MouseEventArgs e) { 
				dragging = false;
				if( stickBorder != StickBorderType.None ) stickControlBorder( container, stickBorder, 20 );
			};
		}
		#endregion
		
		#region Transparent Form		
		
		#region Win32 GDI functions
		/// <summary>
		// a static class to expose needed win32 gdi functions.
		/// </summary>
		class Win32 
		{
			public enum Bool 
			{
				False= 0,
				True
			};
	
			[StructLayout(LayoutKind.Sequential)]
				public struct Point 
			{
				public Int32 x;
				public Int32 y;
	
				public Point(Int32 x, Int32 y) { this.x= x; this.y= y; }
			}
	
			[StructLayout(LayoutKind.Sequential)]
				public struct Size 
			{
				public Int32 cx;
				public Int32 cy;
	
				public Size(Int32 cx, Int32 cy) { this.cx= cx; this.cy= cy; }
			}
	
			[StructLayout(LayoutKind.Sequential, Pack=1)]
				struct ARGB 
			{
				public byte Blue;
				public byte Green;
				public byte Red;
				public byte Alpha;
			}
	
			[StructLayout(LayoutKind.Sequential, Pack=1)]
				public struct BLENDFUNCTION 
			{
				public byte BlendOp;
				public byte BlendFlags;
				public byte SourceConstantAlpha;
				public byte AlphaFormat;
			}
	
	
			public const Int32 ULW_COLORKEY = 0x00000001;
			public const Int32 ULW_ALPHA    = 0x00000002;
			public const Int32 ULW_OPAQUE   = 0x00000004;
	
			public const byte AC_SRC_OVER  = 0x00;
			public const byte AC_SRC_ALPHA = 0x01;
	
	
			[DllImport("user32.dll", ExactSpelling=true, SetLastError=true)]
			public static extern Bool UpdateLayeredWindow(IntPtr hwnd, IntPtr hdcDst, ref Point pptDst, ref Size psize, IntPtr hdcSrc, ref Point pprSrc, Int32 crKey, ref BLENDFUNCTION pblend, Int32 dwFlags);
	
			[DllImport("user32.dll", ExactSpelling=true, SetLastError=true)]
			public static extern IntPtr GetDC(IntPtr hWnd);
	
			[DllImport("user32.dll", ExactSpelling=true)]
			public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
	
			[DllImport("gdi32.dll", ExactSpelling=true, SetLastError=true)]
			public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
	
			[DllImport("gdi32.dll", ExactSpelling=true, SetLastError=true)]
			public static extern Bool DeleteDC(IntPtr hdc);
	
			[DllImport("gdi32.dll", ExactSpelling=true)]
			public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
	
			[DllImport("gdi32.dll", ExactSpelling=true, SetLastError=true)]
			public static extern Bool DeleteObject(IntPtr hObject);
		}
		#endregion
		
		//get image background from Form's background
		public static void setTransparentBackground(Control control, byte opacity){
			Bitmap bitmap = (Bitmap)control.BackgroundImage;
			setTransparentBackground( control, bitmap, opacity );
		}
		
		public static void setTransparentBackground(Control control, string bitmapImage, byte opacity){
			Bitmap bitmap = (Bitmap)Bitmap.FromFile(bitmapImage);
			setTransparentBackground( control, bitmap, opacity );
		}
		
		//resize bitmap to fix form's padding and keep padding border.
		public static void setTransparentBackground(Control control, Bitmap bitmap, byte opacity, Padding padding){
			bitmap = ImageLib.ResizePadding( bitmap, padding, control.Size );
			setTransparentBackground( control, bitmap, opacity );
		}
		
		public static void setTransparentBackground(Control control, Bitmap bitmap, byte opacity){			
			if (bitmap.PixelFormat != PixelFormat.Format32bppArgb)
				throw new ApplicationException("The bitmap must be 32ppp with alpha-channel.");
	
			// The ideia of this is very simple,
			// 1. Create a compatible DC with screen;
			// 2. Select the bitmap with 32bpp with alpha-channel in the compatible DC;
			// 3. Call the UpdateLayeredWindow.
	
			IntPtr screenDc = Win32.GetDC(IntPtr.Zero);
			IntPtr memDc = Win32.CreateCompatibleDC(screenDc);
			IntPtr hBitmap = IntPtr.Zero;
			IntPtr oldBitmap = IntPtr.Zero;
	
			try {
				hBitmap = bitmap.GetHbitmap(Color.FromArgb(0));  // grab a GDI handle from this GDI+ bitmap
				oldBitmap = Win32.SelectObject(memDc, hBitmap);
	
				Win32.Size size 			= new Win32.Size(bitmap.Width, bitmap.Height);
				Win32.Point pointSource 	= new Win32.Point(0, 0);
				Win32.Point topPos 			= new Win32.Point(control.Left, control.Top);
				Win32.BLENDFUNCTION blend 	= new Win32.BLENDFUNCTION();
				blend.BlendOp             	= Win32.AC_SRC_OVER;
				blend.BlendFlags          	= 0;
				blend.SourceConstantAlpha 	= opacity;
				blend.AlphaFormat         	= Win32.AC_SRC_ALPHA;
	
				Win32.UpdateLayeredWindow(control.Handle, screenDc, ref topPos, ref size, memDc, ref pointSource, 0, ref blend, Win32.ULW_ALPHA);
				control.Size = new Size( bitmap.Width, bitmap.Height );
			}
			finally {
				Win32.ReleaseDC(IntPtr.Zero, screenDc);
				if (hBitmap != IntPtr.Zero) {
					Win32.SelectObject(memDc, oldBitmap);
					//Windows.DeleteObject(hBitmap); // The documentation says that we have to use the Windows.DeleteObject... but since there is no such method I use the normal DeleteObject from Win32 GDI and it's working fine without any resource leak.
					Win32.DeleteObject(hBitmap);
				}
				Win32.DeleteDC(memDc);
			}
		}
	
		
		
		
		
		
		public static TransparentForm setTransparentForm( Form form, string bitmapImage, byte opacity, TransparentFormOption options ){
			return new TransparentForm( form, (Bitmap)Bitmap.FromFile(bitmapImage), opacity, options );
		}
		
		public static TransparentForm setTransparentForm( Form form, Bitmap bitmap, byte opacity, TransparentFormOption options ){
			return new TransparentForm( form, bitmap, opacity, options );
		}
		
		//get image background from form background
		public static TransparentForm setTransparentForm( Form form, byte opacity, TransparentFormOption options ){
			return new TransparentForm( form, (Bitmap)form.BackgroundImage, opacity, options );
		}
		
		
		
		public static TransparentForm setTransparentForm( Form form, byte opacity, FormBackground formBg, TransparentFormOption options ){
			Bitmap bitmap;
			switch(formBg)
			{				
				case FormBackground.VistaBlue: 	
					if( options.Padding.All == 0 ) options.Padding	= new Padding(11);
					bitmap 			= (Bitmap)popLibResource.VistaBlue;
					break;							
				case FormBackground.VistaBlueContainer:
					if( options.Padding.All == 0 ) options.Padding	= new Padding(15, 32, 15, 13);
					bitmap 			= (Bitmap)popLibResource.VistaBlueContainer;
					options.AllowTransparentForm = false;
					break;
				case FormBackground.VistaWhite:
					if( options.Padding.All == 0 ) options.Padding	= new Padding(15, 15, 15, 19);
					bitmap 			= (Bitmap)popLibResource.VistaWhite;
					break;
				default: bitmap 	= (Bitmap)popLibResource.VistaWhite; break;
			}
			
			return new TransparentForm( form, bitmap, opacity, options );
		}
		#endregion
		
		#region ApplicationSetting
		public static void initAppSetting(string key, string value){
			System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
			KeyValueConfigurationCollection setting   = config.AppSettings.Settings;
			if( setting[key] == null ) setting.Add(key, value);
			else setting[key].Value = value;
			config.Save( ConfigurationSaveMode.Modified );
		}
		
		public static string getAppSetting(string key){
			System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
			KeyValueConfigurationCollection setting   = config.AppSettings.Settings;
			if( setting[key] != null ){
				return setting[key].Value;			
			}else return null;
		}
		
		
		
		
		public static void setAppSettingINI(string section, string key, string value){			
			setSettingINI( FileLib.getFullPath( Application.ProductName+".ini" ), section, key, value );
		}
		
		public static void setSettingINI( string file, string section, string key, string value){
			INISetting profile = new INISetting(file);
			profile.SetValue( section, key, value );
			profile.Save();
		}
		
		public static string getAppSettingINI( string section, string key, string defaultValue){
			return getSettingINI( FileLib.getFullPath( Application.ProductName+".ini" ), section, key, defaultValue );
		}
				
		public static string getSettingINI(string file, string section, string key, string defaultValue){			
			INISetting profile = new INISetting(file);
			string value = profile.GetValue( section, key, defaultValue );
			profile.Save();
			return value;
		}
		
		#endregion
		#endregion
		
		public static void fillCityControl( object control, string[] cityCode ){
			DataTable city = ConstantStore.getCity(cityCode);
						
			if( FormLib.matchControlType(control, ControlType.ComboBox ) ){
				ComboBox ctrl = (ComboBox)control;
				ctrl.DataSource = city;
				ctrl.DisplayMember = "CITY_NAME";
				ctrl.ValueMember   = "CITY_CODE";
			}else if( FormLib.matchControlType(control, ControlType.ListBox ) ){
				ListBox ctrl = (ListBox)control;
				ctrl.DataSource = city;
				ctrl.DisplayMember = "CITY_NAME";
				ctrl.ValueMember   = "CITY_CODE";
			}else if( FormLib.matchControlType(control, ControlType.CheckedListBox ) ){
				CheckedListBox ctrl = (CheckedListBox)control;
				ctrl.DataSource = city;
				ctrl.DisplayMember = "CITY_NAME";
				ctrl.ValueMember   = "CITY_CODE";
			}
		}
		
		public static void fillDistrictControl( object control, object cityControl ){				
			
			//view district for selected city
			EventHandler IndexChangedEvent = delegate(object sender, EventArgs e) {
				
				
				string cityCode = "";
				if( FormLib.matchControlType(sender, ControlType.ComboBox ) ){
					if( ((ComboBox)sender).SelectedIndex == -1 ) return;
					cityCode = ((ComboBox)sender).SelectedValue.ToString();
				}else if( FormLib.matchControlType(control, ControlType.ListBox ) ){
					if( ((ListBox)sender).SelectedIndex == -1 ) return;
					cityCode = ((ListBox)sender).SelectedValue.ToString();
				}else if( FormLib.matchControlType(control, ControlType.CheckedListBox ) ){
					if( ((CheckedListBox)sender).SelectedIndex == -1 ) return;
					cityCode = ((CheckedListBox)sender).SelectedValue.ToString();
				}
				
				DataTable district = ConstantStore.getDistrictByCity( cityCode );
				
				if( FormLib.matchControlType(control, ControlType.ComboBox ) ){
					ComboBox ctrl = (ComboBox)control;
					ctrl.DataSource = district;
					ctrl.DisplayMember = "DISTRICT_NAME";
					ctrl.ValueMember   = "DISTRICT_CODE";
				}else if( FormLib.matchControlType(control, ControlType.ListBox ) ){
					ListBox ctrl = (ListBox)control;
					ctrl.DataSource = district;
					ctrl.DisplayMember = "DISTRICT_NAME";
					ctrl.ValueMember   = "DISTRICT_CODE";
				}else if( FormLib.matchControlType(control, ControlType.CheckedListBox ) ){
					CheckedListBox ctrl = (CheckedListBox)control;
					ctrl.DataSource = district;
					ctrl.DisplayMember = "DISTRICT_NAME";
					ctrl.ValueMember   = "DISTRICT_CODE";
				}
			};
			
			//add event for city control
			if( FormLib.matchControlType(cityControl, ControlType.ComboBox ) ){
				ComboBox ctrl = (ComboBox)cityControl;
				ctrl.SelectedIndexChanged += IndexChangedEvent;				
			}else if( FormLib.matchControlType(cityControl, ControlType.ListBox ) ){
				ListBox ctrl = (ListBox)cityControl;
				ctrl.SelectedIndexChanged += IndexChangedEvent;				
			}else if( FormLib.matchControlType(cityControl, ControlType.CheckedListBox ) ){
				CheckedListBox ctrl = (CheckedListBox)cityControl;
				ctrl.SelectedIndexChanged += IndexChangedEvent;				
			}
		}
		
		public static void RemoveEventFromControl(Control control, string EventName ){
			FieldInfo fieldInfo = typeof(Control).GetField("Event"+EventName, BindingFlags.Static | BindingFlags.NonPublic);
            object obj = fieldInfo.GetValue(control);	            
            PropertyInfo propertyInfo = control.GetType().GetProperty("Events", BindingFlags.NonPublic | BindingFlags.Instance);	            
            EventHandlerList list = (EventHandlerList)propertyInfo.GetValue(control, null);	            
            list.RemoveHandler(obj, list[obj]);
		}
	 
		public static void DragAndMove( Form mainform, Control container, Control item ){
			int posx = 0;
			int posy = 0;
			
			int disx = 0;
			int disy = 0;
			
			container.AllowDrop = true;
			item.AllowDrop = false;
			//item.Cursor = Cursors.SizeAll;
			
			item.MouseDown += delegate(object sender, MouseEventArgs e) { 
				disx = e.X;
				disy = e.Y;
				mainform.DoDragDrop( item,DragDropEffects.Move );
            };
			
			container.DragEnter += delegate(object sender, DragEventArgs e) { 
				e.Effect = DragDropEffects.Move;
			};
						
			container.DragOver += delegate(object sender, DragEventArgs e) { 
				Point clientp = container.PointToClient(new Point(e.X,e.Y));
				posx = clientp.X - disx;
				posy = clientp.Y - disy;
				
				item.SetBounds(posx, posy, item.Width,item.Height);
				mainform.Refresh();
				mainform.Update();
			};
		}
		
		
		
		public static void PopupFormHotkey(Form form, PopupFormHotkeyType hotkey, bool autoHideWhenLostFocus){
			if(autoHideWhenLostFocus){
				form.Activated += delegate(object sender, EventArgs e) { 
					if(form.Tag != null && form.Tag.ToString() == "NoPopup") return;
					((Form)sender).Opacity = 1;
				};
				
				form.Deactivate += delegate(object sender, EventArgs e) { 
					if(form.Tag != null && form.Tag.ToString() == "NoPopup") return;
					((Form)sender).Hide();
					((Form)sender).Show();
					((Form)sender).SendToBack();
					((Form)sender).Opacity = 0;
				};
			}
			
			APILib.DefWindowProc( form.Handle , APILib.WM_SHOWWINDOW, 0, 0);
			APILib.SendMessage( form.Handle, APILib.WM_SETHOTKEY, (int)hotkey, 0);
		}
		
		public static void PopupFormHotkeyRelease(Form form, bool isRelease){
			form.Tag = isRelease ? "NoPopup" : null;
		}
		
		public static void ExitTimer(Form form, int interval){
			System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
			timer.Tick += delegate { form.Close(); };
			timer.Interval = interval;
			timer.Start();
		}
		
		public static void ApplyMinimumEffect(Form form, NotifyIcon notifyIcon){
			form.SizeChanged += delegate { 
				if( form.WindowState == FormWindowState.Minimized ){
					form.Hide();
				}
			};
			
			notifyIcon.Click += delegate { 
				if( !form.Visible ){
					form.Show();
					if( form.WindowState == FormWindowState.Minimized )
						form.WindowState = FormWindowState.Normal;
					form.BringToFront();
				}else{
					form.Hide();
				}
			};
		}
 	}
 	
 	public enum PopupFormHotkeyType {HK_SHIFTA = 321, HK_SHIFTB = 322, HK_SHIFTZ = 346, HK_CONTROLA = 577, HK_ALTZ = 1114}
 	public enum StickBorderType { All, Left, Top, Bottom, Right, None }
 	public enum FormBackground{ VistaBlue, VistaBlueContainer, VistaWhite }
 	public enum ConfirmButton{ OK, OKCancel, YesNo, YesNoCancel, AbortRetryIgnore, RetryCancel }
	public enum ConfirmResult{ OK, Cancel, Yes, No, Abort, Retry, Ignore, None }
 	public enum ControlType{ None, GroupBox, Panel, TabPage, TextBox, ListBox, ComboBox, DataGrid, DataGridView, CheckBox, Label, Button, DateTimePicker, RadioButton, CheckedListBox, DomainUpDown, FlowLayoutPanel, LinkLabel, ListView, MaskedTextBox, MonthCalendar, NumericUpDown, PictureBox, ProgressBar, PropertyGrid, RichTextBox, SplitContainer, TabControl, TableLayoutPanel, TrackBar, TreeView, WebBrowser, ToolStrip, StatusStrip, SplitterPanel, Timer, ToolStripMenuItem, ToolStripButton, ToolStripSeparator }
	
 	public class MergeHeaderInfo{
		string headerText;
		int leftColumn;
		int rightColumn;
		bool splitRow;
		
		public MergeHeaderInfo(string headerText, int leftColumn, int rightColumn, bool splitRow){
			this.HeaderText 	= headerText;
			this.LeftColumn 	= leftColumn;
			this.rightColumn 	= rightColumn;
			this.SplitRow 	= splitRow;
		}
		
		public string HeaderText{
			get{ return headerText; }
			set{ headerText = value; }
		}
		
		public int LeftColumn{
			get{ return leftColumn; }
			set{ leftColumn = value; }
		}
		
		public int RightColumn{
			get{ return rightColumn; }
			set{ rightColumn = value; }
		}
		
		public bool SplitRow{
			get{ return splitRow; }
			set{ splitRow = value; }
		}
	}
 }
